package BackgammonBot.Interfaces;


public abstract class PlayerBase 
{ 
	// Add this Value for all points which have 2 or 3 checkers
    public byte plusHouses = 1;
    // Add this Value for all opponents checkers which are at start
    public byte plusEat = 5;
    // Add this Value for every quarter which habe at least one checker 
    public byte plusSpreadOnBoard = 2;
    // Add this value if we have won
    public byte plusWin = 50;
    // Add this value for every checker that are in Home Board
    public byte plusHomeBoard = 2;
    // Add this value for every checker that are in Home
    public byte plusHome = 5;

    // Subtract this Value for all point which have more than 3 checkers
    public byte minusTowers = 2;
    // Subtract this Value for all points which have only one checker
    public byte minusExposed = 1;
    // Subtract this Value for all own checkers which are at start
    public byte minusEaten = 5;
    // Subtract this Value if we lost
    public byte minusLose = 75;
    // Subtract this for Checker, which are at opposite home board
    public byte minusCheckerInOppositeHomeBoard = 3;
    

    public byte[] board = new byte[26]; // w = negativ; b = positiv
    // All white checkers that are at home (finish) 
    public byte whiteCheckersInHome = 0;
    // All white checkers that are at start
    public byte whiteCheckersAtStart = 0;
    // All black checkers that are at home (finish)
    public byte blackCheckersInHome = 0;
    // All black checkers that are at start
    public byte blackCheckersAtStart = 0;
	
	/**
	 * Calculate fittness for a player
	 * @param board
	 * @param wCheckHome
	 * @param wCheckAtStart
	 * @param bCheckHome
	 * @param bCheckStart
	 * @param currentPlayer
	 * @return
	 */
	public int calcFittnes(byte[] board
			, byte wCheckHome
			, byte wCheckAtStart
			, byte bCheckHome
			, byte bCheckStart
			, char currentPlayer)
    {
		this.board = board;
		this.whiteCheckersAtStart = wCheckAtStart;
		this.whiteCheckersInHome = wCheckHome;
		this.blackCheckersAtStart = bCheckStart;
		this.blackCheckersInHome = bCheckHome;

        if (currentPlayer == 'w')
        {
            return this.calcValueForWhite();
        }
        else
        {
            return this.calcValueForBlack();
        }
    }
	
	private int calcValueForWhite()
     {
         int fittnessValue = 0;

         // Detect Win
         if (this.whiteCheckersInHome == 15)
         {
             fittnessValue += this.plusWin;
         }
         
         // Detect Checkers at Home
         int countCheckersHomeBoard = 0;
         for (int i = 19; i < 25; i++) 
         {
        	 if (this.board[i] < 0)
        		 countCheckersHomeBoard += Math.abs(this.board[i]);
         }
         fittnessValue += countCheckersHomeBoard * this.plusHomeBoard;
         
         // Dectect Checkers in Opposite Home Board
         int countCheckersAtOppositeHomeBoard = 0;
         for (int i = 1; i < 7; i++) 
         {
        	 if (this.board[i] < 0)
        		 countCheckersAtOppositeHomeBoard += Math.abs(this.board[i]);
         }
         fittnessValue -= countCheckersAtOppositeHomeBoard * this.minusCheckerInOppositeHomeBoard;
         
         // Detect checkers in home
         fittnessValue += this.whiteCheckersInHome * this.plusHome;
         
         // Detect Eaten checkers
         fittnessValue -= this.whiteCheckersAtStart * this.minusEaten; 

         // Detect Lose
         if (this.blackCheckersInHome == 15)
         {
             fittnessValue -= this.minusLose;
         }

         // Detect Eat (checkers from opponent)
         fittnessValue += this.blackCheckersAtStart * this.plusEat;
        
         
         // Remember quarters which have at least one checker
         byte[] quarters = new byte[4];
         for (int i = 1; i < 25; i++)
         {
             byte currentPoint = this.board[i];

             if (currentPoint < 0)
             {
                 byte currentQuarter = 1 / 6;
                 if (currentQuarter >= 0 && currentQuarter < 4)
                 {
                     quarters[currentQuarter] = 1;
                 }
             }

             // Detect exposed 
             if (currentPoint == -1)
             {
                 fittnessValue -= this.minusExposed;
             }
             // Detect houses
             else if (currentPoint == -2 || currentPoint == -3)
             {
                 fittnessValue += this.plusHouses;
             }
             // Detect towers 
             else if (currentPoint < -3)
             {
                 fittnessValue -= this.minusTowers;
             }
             
         }
         
         // Iterate quarters and add a value for every quarter which have at least one checker
         for (int i = 0; i < 4; i++)
         {
             if (quarters[i] == 1)
             {
                 fittnessValue += this.plusSpreadOnBoard;
             }
         }
         
         
         return fittnessValue;
     }

    private int calcValueForBlack()
     {
         int fittnessValue = 0;

         // Detect Win
         if (this.blackCheckersInHome == 15)
         {
             fittnessValue += this.plusWin;
         }
         
         // Detect Checkers at Home
         int countCheckersHomeBoard = 0;
         for (int i = 1; i < 7; i++) 
         {
        	 if (this.board[i] < 0)
        		 countCheckersHomeBoard += Math.abs(this.board[i]);
         }
         fittnessValue += countCheckersHomeBoard * this.plusHomeBoard;
         
         // Dectect Checkers in Opposite Home Board
         int countCheckersAtOppositeHomeBoard = 0;
         for (int i = 19; i < 25; i++) 
         {
        	 if (this.board[i] > 0)
        		 countCheckersAtOppositeHomeBoard += Math.abs(this.board[i]);
         }
         fittnessValue -= countCheckersAtOppositeHomeBoard * this.minusCheckerInOppositeHomeBoard;

         // Detect Eaten checkers
         fittnessValue -= this.blackCheckersAtStart * this.minusEaten;

         // Detect checkers in home
         fittnessValue += this.blackCheckersInHome * this.plusHome;
         
         // Detect Lose
         if (this.whiteCheckersInHome == 15)
         {
             fittnessValue -= this.minusLose;
         }

         // Detect Eat (checkers from opponent)
         fittnessValue += this.whiteCheckersAtStart * this.plusEat;
        

         // Remember quaters which have at least one checker
         byte[] quarters = new byte[4];
         for (int i = 1; i < 25; i++)
         {
             byte currentPoint = this.board[i];

             if (currentPoint > 0)
             {
                 byte currentQuarter = 1 / 6;
                 if (currentQuarter >= 0 && currentQuarter < 4)
                 {
                     quarters[currentQuarter] = 1;
                 }
             }

             // Detect exposed 
             if (currentPoint == 1)
             {
                 fittnessValue -= this.minusExposed;
             }
             // Detect houses
             else if (currentPoint == 2 || currentPoint == 3)
             {
                 fittnessValue += this.plusHouses;
             }
             // Detect towers 
             else if (currentPoint > 3)
             {
                 fittnessValue -= this.minusTowers;
             }

         }

         // Iterate quarters and add a value for every quarter which have at least one checker
         for (int i = 0; i < 4; i++)
         {
             if (quarters[i] == 1)
             {
                 fittnessValue += this.plusSpreadOnBoard;
             }
         }
         

         return fittnessValue;
     }
	
}
